#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <jsoncpp/json/json.h>

#define Myself

#define blank_space_protocol " " // 有效数据中每个数据用空格隔开
#define protocol "\n"            // 期望获得的数据格式为: "len"\n"a + b"\n

//为字符串添加报头
std::string Encode(std::string& content)
{
    size_t len = content.size();

    std::string package = to_string(len);
    package += protocol;
    package += content;
    package += protocol;

    return package;
}

// 为字符串去掉报头
// "len"\n"xxxxx"\n"len"\n"xxxxx"\n"len"\n"xxxxx"\n"len"\n"xxxxx"\n
bool Decode(std::string& package, std::string* content)
{
    // 先确定这一批报文中第一个报文的大小
    size_t pos = package.find(protocol);
    if(pos == std::string::npos) return false;
    std::string len_str = package.substr(0, pos);   // len_str.size()是报头的长度
    size_t message_len = std::stoi(len_str);             // 正文的有效长度
    size_t len = len_str.size() + message_len + 2;  // 第一个报文的全部长度

    // 如果这一批报文的总长度小于第一个报文的长度那就肯定有问题
    if(package.size() < len){return false;}

    *content = package.substr(pos + 1, message_len); // 让content获得第一个正文

    // 移除掉已经读了的报文
    package.erase(0, len);

    return true;
}


class Request
{
public:
    Request(int x, int y, char op)
    :x_(x), y_(y), op_(op)
    {}
    Request()
    {}
    ~Request()
    {}

public:
    // "a + b"
    bool Serialize(std::string* content) // 序列化:将结构体成员转化为字符串
    {
#ifdef Myself
        std::string out = std::to_string(x_);
        out += blank_space_protocol;
        out += op_;
        out += blank_space_protocol;
        out += std::to_string(y_);

        *content = out;
#else 
        Json::Value out;
        out["x"] = x_;
        out["y"] = y_;
        out["op"] = op_;
        Json::FastWriter w;
        *content = w.write(out);
#endif
        return true;
    }

    // "len"\n"a + b"\n
    // 先调用Decode函数把报头去掉,就能获得有效正文
    // "a + b"
    bool Deserialize(std::string package) // 反序列化:将字符串转化为结构体成员
    {
#ifdef Myself
        size_t leftblank = package.find(blank_space_protocol);
        size_t rightblank = package.rfind(blank_space_protocol);
        if(leftblank == std::string::npos || rightblank == std::string::npos){return false;}

        x_  = std::stoi(package.substr(0, leftblank));
        op_ = package[leftblank + 1];
        y_  = std::stoi(package.substr(rightblank + 1));
#else
        Json::Value root;
        Json::Reader r;
        r.parse(package, root);

        x_  = root["x"].asInt();
        y_  = root["y"].asInt();
        op_ = root["op"].asInt();
#endif
        return true;
    }

    void DebugPrint()
    {
        std::cout << "新请求构建完成:  " << x_ << op_ << y_ << "=?" << std::endl;
    }
public:
    int x_;
    int y_;
    char op_;
};

class Response
{
public:
    Response(int result, int code)
    :result_(result), code_(code)
    {}
    Response()
    {}
    ~Response()
    {}
public:
    //1000 0
    bool Serialize(std::string* content)
    {
#ifdef Myself
        std::string out = std::to_string(result_);
        out += blank_space_protocol;
        out += std::to_string(code_);
        
        *content = out;
#else
        Json::Value out;
        out["result"] = result_;
        out["code"] = code_;
        
        Json::FastWriter w;
        *content = w.write(out);
#endif
        return true;
    }
    // "len"\n"1000 0"\n
    // "1000 0"
    bool Deserialize(std::string package)
    {
#ifdef Myself
        size_t blank = package.find(blank_space_protocol);
        if(blank == std::string::npos){return false;}

        result_  = std::stoi(package.substr(0, blank));
        code_    = std::stoi(package.substr(blank + 1));
#else
        Json::Value root;
        Json::Reader r;
        r.parse(package, root);

        result_  = root["result"].asInt();
        code_  = root["code"].asInt();
#endif
        return true;
    }

    void DebugPrint()
    {
        std::cout << "结果响应完成, result: " << result_ << ", code: "<< code_ << std::endl;
    }

public:
    int result_;
    int code_;
};